//
//  KColumnInfo.m
//  MengLiao
//
//  Created by xiuxin on 2022/7/15.
//  Copyright © 2022 ZHBen. All rights reserved.
//

#import "KColumnInfo.h"
#import <objc/runtime.h>
#import "NSObject+KObserverHelper.h"

@interface KColumnInfo()

@property (nonatomic) BOOL setOffsetFlag;

@property (nonatomic) BOOL kvoFlag;

@property (weak,nonatomic) UIView * contentView;

@property (nonatomic) KDisplayPosition frontPosition;

@property (nonatomic) BOOL cellIsValid;

@property (strong,nonatomic) NSTimer * showInCellTimer;

@property (nonatomic) BOOL enabled;

@property (nonatomic) CGFloat scrollContentHeight;

@end

@implementation KColumnInfo
@dynamic frontPosition;

- (instancetype)init
{
    if (self = [super init])
    {
        _enabled = YES;
    }
    return self;
}

- (instancetype)initWithColumnView:(UIView<KColumnContentView> *)columnView
{
    if (self = [self init])
    {
        self.columnView = columnView;
        _view = columnView;
    }
    return self;
}

- (BOOL)refreshItemSize
{
    if (self.view != nil && self.scroll != nil)
    {
        CGFloat extraHeight = CGRectGetHeight(self.view.frame) - CGRectGetHeight(self.scroll.frame);
        CGSize itemSize = CGSizeMake(CGRectGetWidth(self.view.frame), self.scroll.contentSize.height + extraHeight);
        if (self.view != self.columnView)
        {
            itemSize.height = MAX(CGRectGetHeight(self.view.frame), itemSize.height);
        }
        if (fabs(self.itemSize.height - itemSize.height) > .5f)
        {
            _itemSize = itemSize;
            return YES;
        }
    }
    return NO;
}

- (void)beginShowInCellTimer
{
    [self stopShowInCellTimer];
    self.showInCellTimer = [NSTimer timerWithTimeInterval:.1 target:self selector:@selector(checkAndShowInCell:) userInfo:nil repeats:YES];
    [[NSRunLoop mainRunLoop] addTimer:self.showInCellTimer forMode:NSRunLoopCommonModes];
}

- (void)stopShowInCellTimer
{
    [self.showInCellTimer invalidate];
    self.showInCellTimer = nil;
}

- (BOOL)checkAndShowInFront
{
    if (self.displayPosition != KDisplayNone)
    {
        if (self.view.superview != self.containerView.superview)
        {
            [self.view removeFromSuperview];
            [self refreshFrontFrame];
            [self.containerView.superview insertSubview:self.view aboveSubview:self.containerView];
            self.frontPosition = self.displayPosition;
            self.cellIsValid = NO;
        }
    }
    return self.frontPosition != KDisplayNone;
}

- (void)showInCell
{
    if (self.enabled)
    {
        if (self.frontPosition != KDisplayNone)
        {
            [self beginShowInCellTimer];
        }
    }
}

- (void)checkAndShowInCell:(NSTimer *)timer
{
    if (self.view.superview != self.contentView && [self checkCellIsValid])
    {
        if (self.frontPosition == KDisplayFullScreen)
        {
            CGFloat offsetY = CGRectGetMinY(self.cell.frame) + self.scroll.contentOffset.y - self.displayInsets.top;
            if (fabs(offsetY - self.containerView.contentOffset.y) > 0.5f)
            {
                [self.containerView setContentOffset:CGPointMake(0, offsetY) animated:NO];
                //如果Contaienr offset需要调整 等待timer下次运行 保证offset正确、防止抖动
                return;
            }
        }
        [self.view removeFromSuperview];
        [self refreshDisplay];
        [self.contentView addSubview:self.view];
        self.cellIsValid = YES;
    }
    if (self.cellIsValid && self.view.superview == self.contentView)
    {
        self.frontPosition = KDisplayNone;
        [self stopShowInCellTimer];
    }
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(UIScrollView *)view change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context
{
    if (self.enabled)
    {
        if ([keyPath isEqualToString:@"contentSize"])
        {
            if (self.scrollContentHeight != view.contentSize.height)
            {
                self.scrollContentHeight = view.contentSize.height;
                [self contentSizeChanged:view];
            }
        }
        else if ([keyPath isEqualToString:@"contentOffset"])
        {
            [self contentOffsetChanged:view];
        }
    }
}

- (void)contentSizeChanged:(UIScrollView *)scroll
{
    if (self.enabled)
    {
//        [self checkAndShowInFront];
        if ([self refreshItemSize])
        {
            self.cellIsValid = NO;
            [self.control reloadColumn:self];
        }
    }
}

- (void)contentOffsetChanged:(UIScrollView *)scroll
{
    if (self.enabled && self.cellIsValid && !self.setOffsetFlag)
    {
        if ([self.columnView respondsToSelector:@selector(disableOffsetChange)] && [self.columnView disableOffsetChange])
        {
            return;
        }
        if (self.displayPosition == KDisplayTop && scroll.contentOffset.y <= 0.01f)
        {
            return;
        }
        else if (self.displayPosition == KDisplayBottom && scroll.contentOffset.y >= self.itemSize.height - CGRectGetHeight(self.view.frame) - 0.01f)
        {
            return;
        }
        else
        {
            CGFloat offsetY = CGRectGetMinY(self.cell.frame) + scroll.contentOffset.y - self.displayInsets.top;
            if (fabs(self.containerView.contentOffset.y - offsetY) > 0.5f)
            {
                [self.containerView setContentOffset:CGPointMake(0, offsetY)];
            }
        }
    }
}

- (void)refreshDisplay
{
    [self refreshDisplayPosition];
    [self refreshScrollOffset];
    [self refreshViewFrame];
}

- (void)cellWillDisplay:(__kindof UIView *)cell contentView:(UIView *)contentView
{
    if (self.cell != cell)
    {
        self.contentView = contentView;
        self.cell = cell;
        self.cellIsValid = NO;
    }
    if (!self.cellIsValid)
    {
        [self containerOffsetChanged];
    }
}

- (void)cellDidEndDisplay:(__kindof UIView *)cell
{
    if (self.cell == cell)
    {
        if (self.displayPosition != KDisplayFullScreen)
        {
            self.displayPosition = KDisplayNone;
        }
        self.cell = nil;
        self.contentView = nil;
        self.cellIsValid = NO;
//        [self stopShowInCellTimer];
    }
}

- (void)refreshDisplayPosition
{
    if ((self.containerView.contentOffset.y + self.displayInsets.top) < CGRectGetMinY(self.cell.frame) - 0.1f)
    {
        self.displayPosition = KDisplayTop;
    }
    else if (self.containerView.contentOffset.y + CGRectGetHeight(self.containerView.frame) - self.displayInsets.bottom > CGRectGetMaxY(self.cell.frame)  + 0.1f)
    {
        self.displayPosition = KDisplayBottom;
    }
    else
    {
        self.displayPosition = KDisplayFullScreen;
    }
}

- (void)refreshScrollOffset
{
    if (self.displayPosition == KDisplayTop)
    {
        [self setScrollOffset:CGPointZero];
    }
    else if (self.displayPosition == KDisplayFullScreen)
    {
        [self setScrollOffset:CGPointMake(0, self.containerView.contentOffset.y + self.displayInsets.top - CGRectGetMinY(self.cell.frame))];
    }
    else if (self.displayPosition == KDisplayBottom)
    {
//        CGFloat offsetY = self.containerView.contentOffset.y - CGRectGetMinY(self.cell.frame);
//        offsetY = MAX(offsetY, self.scroll.contentSize.height - CGRectGetHeight(self.scroll.bounds));
//        [self setScrollOffset:CGPointMake(0, offsetY)];
        [self setScrollOffset:CGPointMake(0, CGRectGetHeight(self.cell.frame) -  CGRectGetHeight(self.view.frame))];
    }
}

- (void)refreshViewFrame
{
    CGRect frame = self.view.frame;
    frame.origin.y = self.scroll.contentOffset.y;
    if (self.displayPosition == KDisplayBottom)
    {
        frame.origin.y = MIN(frame.origin.y, CGRectGetHeight(self.cell.frame) -  CGRectGetHeight(self.view.frame));
    }
    frame.origin.x = 0.0f;
    self.view.frame = frame;
}

- (void)setScrollOffset:(CGPoint)offset
{
    self.setOffsetFlag = YES;
    self.scroll.contentOffset = offset;
    self.setOffsetFlag = NO;
}

- (void)refreshFrontFrame
{
    CGRect frame = self.view.frame;
    frame.origin.y = frame.origin.y + self.cell.frame.origin.y - self.containerView.contentOffset.y + self.containerView.frame.origin.y;
    frame.origin.x = self.containerView.frame.origin.x;
    self.view.frame = frame;
}

- (KDisplayPosition)displayPosition
{
    if (_cell != nil)
    {
        return [objc_getAssociatedObject(_cell, _cmd) unsignedIntegerValue];
    }
    return KDisplayNone;
}

- (void)setDisplayPosition:(KDisplayPosition)displayPosition
{
    if (_cell != nil)
    {
        if (displayPosition != [objc_getAssociatedObject(_cell, @selector(displayPosition)) unsignedIntegerValue])
        {
            objc_setAssociatedObject(_cell, @selector(displayPosition), [NSNumber numberWithUnsignedInteger:displayPosition], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
            [self.control columnInfo:self displayPositionChanged:displayPosition];
        }
    }
}

- (KDisplayPosition)frontPosition
{
    if (_view != nil)
    {
        return [objc_getAssociatedObject(_view, _cmd) unsignedIntegerValue];
    }
    return NO;
}

- (void)setFrontPosition:(KDisplayPosition)frontPosition
{
    if (_view != nil)
    {
        objc_setAssociatedObject(_view, @selector(frontPosition), [NSNumber numberWithUnsignedInteger:frontPosition], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }
}

- (BOOL)checkCellIsValid
{
    if (self.cell.window != nil && !self.cell.isHidden)
    {
        if ([self refreshItemSize])
        {
            [self.control reloadColumn:self];
            return NO;
        }
        if (fabs(self.itemSize.height - CGRectGetHeight(self.cell.frame)) < 0.5f)
        {
            return YES;
        }
    }
    return NO;
}

- (void)setCell:(__kindof UIView *)cell
{
    if (cell != _cell)
    {
        _cell = cell;
        if (_cell != nil)
        {
            [self startKVO];
        }
        else
        {
            [self stopKVO];
        }
    }
}

- (void)containerOffsetChanged
{
    if (self.enabled)
    {
        if (self.cellIsValid)
        {
            [self refreshDisplay];
        }
        else if (self.frontPosition == KDisplayNone && [self checkCellIsValid])
        {
            [self refreshDisplay];
            if (self.view.superview != self.contentView)
            {
                [self.contentView.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];
                [self.contentView addSubview:self.view];
            }
            if (CGRectGetHeight(self.view.frame) > CGRectGetHeight(self.contentView.frame) + .5f)
            {
                [self setScrollOffset:CGPointZero];
                self.view.frame = self.contentView.bounds;
            }
            self.cellIsValid = YES;
        }
    }
}

- (void)setColumnView:(UIView<KColumnContentView> *)columnView
{
    _columnView = columnView;
    if ([columnView respondsToSelector:@selector(scrollView)])
    {
        _scroll = columnView.scrollView;
        _scroll.scrollsToTop = NO;
        _scroll.scrollEnabled = NO;
    }
    else
    {
        _scroll = nil;
    }
}

- (UIScrollView *)containerView
{
    return self.control.containerView;
}

- (void)startKVO
{
    if (!self.kvoFlag && self.scroll != nil)
    {
        [self.scroll k_addObserver:self forKeyPath:@"contentSize" options:NSKeyValueObservingOptionNew context:nil];
        [self.scroll k_addObserver:self forKeyPath:@"contentOffset"
                            options:NSKeyValueObservingOptionNew context:nil];
        self.kvoFlag = YES;
    }
}

- (void)stopKVO
{
    if (self.kvoFlag)
    {
        [self.scroll k_removeObserver:self forKeyPath:@"contentSize" context:nil];
        [self.scroll k_removeObserver:self forKeyPath:@"contentOffset" context:nil];
        self.kvoFlag = NO;
    }
}

- (void)dealloc
{
    [self stopKVO];
}

@end
